//----------------------------------------------------------------------------------------
// @Project Includes
#include "includes.h"

//----------------------------------------------------------------------------------------
// @Local Macro Define in the module

//----------------------------------------------------------------------------------------
// @Local Type defines in the module

//----------------------------------------------------------------------------------------
// @Global Variables define in the module

//----------------------------------------------------------------------------------------
// @Prototypes of functions in the module
static void drv_i2c_delay(uint8_t Dlytype);

static void drv_i2c_sendStart(void);
static void drv_i2c_sendBit(uint8_t uData);
static void drv_i2c_sendByte(uint8_t uVal);
static uint8_t drv_i2c_receByte(void);
static bool_t drv_i2c_receAck(void);
static void drv_i2c_sendAck(void);
static void drv_i2c_sendNack(void);
static void drv_i2c_sendStop(void);

//----------------------------------------------------------------------------------------
/**
 * @brief  i2c delay fun
 * @param  Dlytype: dely type
 * @return none
 * @note   none
 */
static void drv_i2c_delay(uint8_t Dlytype)
{
    volatile uint16_t   u16i;
	
    if(Dlytype == 0)
    {
				u16i = (48)/2;
    }
    else if (Dlytype == 1)/*SCL L*/
    {
				u16i = (64+8)/2;
    }
		else if (Dlytype == 2)/*SCL H*/
		{
		    u16i = (64-4)/2;
		}
		else 
		{
				u16i = (32)/2;
		}	
    while (u16i--);
}

/**
 * @brief  i2c send start
 * @param  none
 * @return none
 * @note   none
 */
static void drv_i2c_sendStart(void)
{
    I2C_SDA_HIGH(); 
    drv_i2c_delay(0);
    
    I2C_SCL_HIGH();
    drv_i2c_delay(0);
    
    I2C_SDA_LOW(); 
    drv_i2c_delay(0);

    I2C_SCL_LOW(); 
    drv_i2c_delay(0);
}

/**
 * @brief  i2c send bit
 * @param  uData :data
 * @return none
 * @note   none
 */
static void drv_i2c_sendBit(uint8_t uData)
{
    if (uData & 0x80)
    {
        I2C_SDA_HIGH();
    }
    else
    {
        I2C_SDA_LOW();
    }
    drv_i2c_delay(3);

    I2C_SCL_HIGH();    
    drv_i2c_delay(2);

    I2C_SCL_LOW();
    drv_i2c_delay(3);
}

/**
 * @brief  i2c send byte
 * @param  uVal :data
 * @return none
 * @note   none
 */
static void drv_i2c_sendByte(uint8_t uVal)
{
    uint8_t  u8i;

    for (u8i = 0; u8i < 8; u8i++)
    {
        drv_i2c_sendBit(uVal);
        uVal <<= 1;
    }    
}

/**
 * @brief  i2c receive byte
 * @param  none
 * @return byte
 * @note   none
 */
static uint8_t drv_i2c_receByte(void)
{
    uint16_t  u16Data;  
    uint8_t   u8i;

    I2C_SDA_HIGH();   
    //drv_i2c_delay(0);
    drv_gpio_outputInit (I2C_SDA_PORT, I2C_SDA_PIN,GPIO_Mode_Input);   
    u16Data = 0;
    for (u8i = 0; u8i < 8; u8i++)
    {
        I2C_SCL_HIGH();   
        drv_i2c_delay(2);
        if (I2C_SDA_READPIN() != RESET)  
        {
            u16Data |= 0X01;
        }
        u16Data <<= 1;   

        I2C_SCL_LOW();
				if (u8i != 7)
				{
            drv_i2c_delay(1); 
				}
    }
    u16Data >>= 1;                    
    drv_gpio_outputInit (I2C_SDA_PORT, I2C_SDA_PIN,GPIO_Mode_Out_PP);
    //drv_i2c_delay(0);		
    return  (uint8_t)u16Data;
}

/**
 * @brief  i2c receive ack
 * @param  none
 * @return true or false
 * @note   none
 */
static bool_t drv_i2c_receAck(void)
{
    bool_t  bresult;

    I2C_SDA_HIGH();   
    //drv_i2c_delay(0);
    drv_gpio_outputInit (I2C_SDA_PORT, I2C_SDA_PIN,GPIO_Mode_Input);
    I2C_SCL_HIGH();          
    drv_i2c_delay(2);

    if (I2C_SDA_READPIN() != RESET)   
    {
        bresult = false;
    }
    else
    {
        bresult = true;
    }

    I2C_SCL_LOW();      
    drv_i2c_delay(3);
    drv_gpio_outputInit (I2C_SDA_PORT, I2C_SDA_PIN,GPIO_Mode_Out_PP); 
	  //drv_i2c_delay(0);
    return (bresult);    
}

/**
 * @brief  i2c send ack
 * @param  none
 * @return none
 * @note   none
 */
static void drv_i2c_sendAck(void)
{
    I2C_SDA_LOW();
    drv_i2c_delay(3);

    I2C_SCL_HIGH();
    drv_i2c_delay(2);

    I2C_SCL_LOW();
    drv_i2c_delay(3);
}

/**
 * @brief  i2c send nack
 * @param  none
 * @return none
 * @note   none
 */
static void drv_i2c_sendNack(void)
{
    I2C_SDA_HIGH();
    drv_i2c_delay(3);

    I2C_SCL_HIGH();
    drv_i2c_delay(2);

    I2C_SCL_LOW();
    drv_i2c_delay(3);
}

/**
 * @brief  i2c send stop
 * @param  none
 * @return none
 * @note   none
 */
static void drv_i2c_sendStop(void)
{
    I2C_SDA_LOW();    
    drv_i2c_delay(0);

    I2C_SCL_HIGH();   
    drv_i2c_delay(1);

    I2C_SDA_HIGH();    
    drv_i2c_delay(0);   
}

/**
 * @brief  i2c write data
 * @param  uDeviceAddr device address
 *       	 uCellAddr   cell address
 *      	 puBuf       buf
 *       	 uNum        the num	
 * @return false or true
 * @note   none
 */
bool_t drv_i2c_write(uint8_t uDeviceAddr, uint8_t uCellAddr, uint8_t * puBuf, uint8_t uNum)
{
    if (uNum != 2)
    {
        return false;
    }

    drv_i2c_sendStart();  

    drv_i2c_sendByte(uDeviceAddr & 0XFE); 
    if (drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    drv_i2c_sendByte(uCellAddr); 
    if (drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    while (uNum--)  
    {
        drv_i2c_sendByte(*puBuf++);
        if (drv_i2c_receAck() == false)
        {
            drv_i2c_sendStop();
            return false;
        }
    }
    drv_i2c_sendStop();

    return true;
}

/**
 * @brief  i2c read data
 * @param  uDeviceAddr device address
 *       	 uCellAddr   cell address
 *      	 puBuf       buf
 *       	 uNum        the num	
 * @return false or true
 * @note   none
 */
bool_t drv_i2c_read(uint8_t uDeviceAddr, uint8_t uCellAddr, uint8_t * puBuf, uint8_t uNum)
{
    if (uNum == 0) 
    {
        return false;
    }

    drv_i2c_sendStart();  

    drv_i2c_sendByte(uDeviceAddr & 0XFE); 
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    drv_i2c_sendByte(uCellAddr); 
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    drv_i2c_sendStart();  

    drv_i2c_sendByte(uDeviceAddr | 0x01); 
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    while (uNum--) 
    {
        *puBuf++ = drv_i2c_receByte();
        if(uNum)
        {
            drv_i2c_sendAck();
        }
        else
        {
            drv_i2c_sendNack();
        }
    }
    drv_i2c_sendStop();

    return true;
}

/**
 * @brief  i2c read data
 * @param  uDeviceAddr device address
 *       	 uCellAddr   cell address
 *      	 puBuf       buf
 * @return false or true
 * @note   none
 */
bool_t drv_i2c_readSh367306(uint8_t uDeviceAddr, uint8_t uCellAddr, uint16_t * puBuf)
{
    uint8_t  Temp[3];
	
    drv_i2c_sendStart();                  

    drv_i2c_sendByte(uDeviceAddr & 0XFE);   
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }
	
    drv_i2c_sendByte(uCellAddr);     
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }
	
    drv_i2c_sendStart();                 

    drv_i2c_sendByte(uDeviceAddr | 0x01);  
    if(drv_i2c_receAck() == false)
    {
        drv_i2c_sendStop();
        return false;
    }

    Temp[0] = drv_i2c_receByte();
    drv_i2c_sendAck();
    Temp[1] = drv_i2c_receByte();
    drv_i2c_sendAck();
    Temp[2] = drv_i2c_receByte();	
    drv_i2c_sendNack();
    drv_i2c_sendStop();

    *puBuf = ((uint16_t)Temp[0]<< 8 | Temp[1]);

    return true;
}

/**
 * @brief  dvc read data
 * @param  writeData write data
 *       	 writeLen  write len
 *      	 readData  read data
 *       	 readLen   read len
 * @return false or true
 * @note   none
 */
bool_t drv_i2c_dvcTransferData(uint8_t *writeData, uint16_t writeLen, uint8_t *readData, uint16_t readLen)
{
		uint8_t slaveRdAddr = writeData[0];

    if (writeLen < 2)    
    {
        return false;
    }
	
    drv_i2c_sendStart();  

    while (writeLen--)  
    {
        drv_i2c_sendByte(*writeData++);
        if (drv_i2c_receAck() == false)
        {
            drv_i2c_sendStop();
            return false;
        }
    }
    if (readLen > 0)
    {
        drv_i2c_sendStart(); 

	      drv_i2c_sendByte(slaveRdAddr| 0x01);  
        if(drv_i2c_receAck() == false)
        {
            drv_i2c_sendStop();
            return false;
        }
        while (readLen--) 
        {
            *readData++ = drv_i2c_receByte();
            if(readLen)
            {
                drv_i2c_sendAck();
            }
            else
            {
                drv_i2c_sendNack();
            }
        }
		
    }
	
    drv_i2c_sendStop();
	
		return true;

}

/**
 * @brief  driver i2c sleep
 * @param  none
 * @return none
 * @note   none
 */
void drv_i2c_sleep(void)
{
		I2C_SDA_HIGH();
		I2C_SCL_HIGH();


}

/**
 * @brief  driver i2c wakeup
 * @param  none
 * @return none
 * @note   none
 */
void drv_i2c_wakeup(void)
{
		drv_i2c_init();	
}

/**
 * @brief  driver i2c initialization
 * @param  none
 * @return none
 * @note   none
 */
void drv_i2c_init(void)
{
    drv_gpio_outputInit (I2C_SCL_PORT, I2C_SCL_PIN,GPIO_Mode_Out_PP);
    drv_gpio_outputInit (I2C_SDA_PORT, I2C_SDA_PIN,GPIO_Mode_Out_PP);
	
		//I2C_SDA_LOW();
		//I2C_SCL_HIGH();
		//TS1_SET();
	  //drv_systick_delay_ms(2);
		//TS1_RESET();
	
		drv_i2c_sendStop();

}

// =======================================================================================
// End of file.
// =======================================================================================
